package com.cirnoworks.uhs.server;

import java.io.IOException;
import java.nio.channels.Selector;
import java.util.HashSet;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import com.cirnoworks.uhs.Link;
import com.cirnoworks.uhs.LinkContainer;
import com.cirnoworks.uhs.LinkManager;

@Singleton
public class ServerContainer extends LinkContainer implements LinkManager {

	private static org.slf4j.Logger LOG = org.slf4j.LoggerFactory
			.getLogger(ServerContainer.class);

	private ControlLink controlLink;

	@Inject
	private UserManager userManager;

	private int port;

	@Inject
	public void setPortStr(@Named("uhs.server.port") String sPort) {
		port = Integer.parseInt(sPort);
	}

	public User getUser(UserKey key) {
		return userManager.getUser(key);
	}

	@Override
	protected void initLinks(Selector selector) {
		try {
			controlLink = new ControlLink(this, selector, port);
			LOG.info("Server listened on " + port);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected void closeLinks(Selector selector) {
		LOG.info("Closing control link...");
		try {
			controlLink.close();
		} catch (IOException e) {
			LOG.error("Error closing control link", e);
		}
		LOG.info("Closing control link...done");
		LOG.info("Closing links..."+links.size());
		Link[] allLinks=links.toArray(new Link[links.size()]);
		for (Link link : allLinks) {
			try {
				link.close();
			} catch (Exception e) {
				LOG.error("Error closing link" + link, e);
			}
		}
		LOG.info("Closing links...done");
	}

	@Override
	public void afterSelect() {
		controlLink.sessionCheck();
	}

	private final HashSet<Link> links = new HashSet<Link>();

	@Override
	public void registerLink(Link link) {
		links.add(link);
	}

	@Override
	public void onLinkClosed(Link link) {
		links.remove(link);
	}
}
